﻿using System;

namespace ExFlash
{
    public static class BitUtil
    {
        public static int GetInt32(Byte[] source, int byteOffset, int bitOffset, int count)
        {
            int retValue = (int)GetUInt32(source, byteOffset, bitOffset, count);

            if ((retValue & (1L << (count - 1))) > 0)
            {
                retValue |= -1 << count;
            }

            return retValue;
        }

        public static uint GetUInt32(Byte[] source, int byteOffset, int bitOffset, int count)
        {
            if (count > 32 || count <= 0)
                return 0;

            if (bitOffset > 8)
            {
                byteOffset += bitOffset / 8;
                bitOffset = bitOffset % 8;
            }

            uint retValue = 0;
            Byte bitBuf = (byte)(source[byteOffset] & (0xFF >> bitOffset));
            int bitPos = 8 - bitOffset;

            while (count > bitPos)
            {
                count -= bitPos;
                retValue |= (uint)bitBuf << count;
                byteOffset++;
                bitBuf = source[byteOffset];
                bitPos = 8;
            }

            bitPos -= count;
            retValue |= (uint) bitBuf >> bitPos;

            return retValue;
        }

        public static float GetFloat(Byte[] source, int byteOffset, int bitOffset, int count)
        {
            int temp = GetInt32(source, byteOffset, bitOffset, count);

            return (float)((temp >> 16) + ((temp & 0xFFFF) / Math.Pow(2, 16)));
        }

        public static Boolean GetBoolean(Byte[] source, int byteOffset, int bitOffset)
        {
            if (bitOffset > 8)
            {
                byteOffset += bitOffset / 8;
                bitOffset = bitOffset % 8;
            }

            return ((source[byteOffset] >> ( 7 - bitOffset)) & 0x1) > 0;
        }

        public static void AdvanceByteOffset(ref int byteOffset, int bitOffset)
        {
            if (bitOffset > 0)
            {
                byteOffset += (bitOffset - 1) / 8 + 1;
            }
        }
    }
}
